package thread;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import cache.NioSelectorPool;
import cache.SynchronizedStack;
import cachedata.NioChannel;
import config.SocketProperties;
import config.SystemConfig;

public class Lift {
	
	private static volatile boolean running = false;

	private String name = "TP";
	
	private SynchronizedStack<ProccessWorker> processorCache;
	
	private SynchronizedStack<PollerEvent> eventCache;
	
	private SynchronizedStack<NioChannel> nioChannels;
	
	private ExecutorService executor;
	
	private Poller[] pollers;
	
	private Acceptor[] acceptors;
	
	private ServerSocketChannel serverSock;
	
	 private NioSelectorPool selectorPool = new NioSelectorPool();
	
	public void bind() throws IOException{
		  	serverSock = ServerSocketChannel.open();
	        SocketProperties.getInstance().setProperties(serverSock.socket());
	        InetSocketAddress addr = new InetSocketAddress(SystemConfig.address,SystemConfig.port);
	        serverSock.socket().bind(addr,200);
	        serverSock.configureBlocking(true); 
	        serverSock.socket().setSoTimeout(3000);
	        selectorPool.open();
	}
	
	public void init(){
		processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
				SystemConfig.processorCache);
        eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
        		SystemConfig.processorCache);
        nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
        		SystemConfig.processorCache);
        
       executor = Executors.newFixedThreadPool(SystemConfig.workThreadNum);
       
       pollers = new Poller[SystemConfig.pollerThreadCount];
       
       for (int i=0; i<pollers.length; i++) {
           pollers[i] = new Poller(selectorPool, executor, eventCache, processorCache);
           Thread pollerThread = new Thread(pollers[i], name + "-ClientPoller-"+i);
           pollerThread.setPriority(5);
           pollerThread.setDaemon(true);
           pollerThread.start();
       }
       
       startAcceptorThreads();
	}

	private void startAcceptorThreads() {
		 int count = SystemConfig.acceptThreadCount;
	        acceptors = new Acceptor[count];

	        for (int i = 0; i < count; i++) {
	            String threadName = name + "-Acceptor-" + i;
	            acceptors[i] = new Acceptor(serverSock, threadName, pollers, nioChannels);
	            acceptors[i].setThreadName(threadName);
	            Thread t = new Thread(acceptors[i], threadName);
	            t.setPriority(5);
	            t.setDaemon(true);
	            t.start();
	        }
	}

	public static boolean isRunning() {
		return running;
	}

	public NioSelectorPool getSelectorPool() {
		return selectorPool;
	}
	
}
